import { log } from '../aop/log';
import MediaStreamConfigure from '../config/MediaStreamConfigure';
import { IAudioConstraints, IVideoConstraints } from '../interface';

class MediaDeviceDao {
	public static audioInput: MediaDeviceInfo[] = [];
	public static audioOutput: MediaDeviceInfo[] = [];
	public static videoInput: MediaDeviceInfo[] = [];
	public static videoOutput: MediaDeviceInfo[] = [];

	public static videoInputDeviceId: string | undefined = undefined;
	public static videoOutputDeviceId: string | undefined = undefined;
	public static audioInputDeviceId: string | undefined = undefined;
	public static audioOutputDeviceId: string | undefined = undefined;

	public static audioStreamConstraints: IAudioConstraints;
	public static videoStreamConstraints: IVideoConstraints;
	public static allMediaDevicesMap: Map<string, MediaDeviceInfo> = new Map();
	public static validMediaDevicesMap: Map<string, MediaDeviceInfo> = new Map();
	public static communicationsMap: Map<string, MediaDeviceInfo> = new Map();

	public static localStream: MediaStream | null = null;

	public static publishOptions = MediaStreamConfigure.defaultPublishOptions;

	@log('日志消息')
	public static setAudioStreamConstraints(constraints: IAudioConstraints) {
		MediaDeviceDao.audioStreamConstraints = { ...MediaDeviceDao.audioStreamConstraints, ...constraints };
		return MediaDeviceDao.audioStreamConstraints;
	}

	@log('日志消息')
	public static setVideoStreamConstraints(constraints: IVideoConstraints) {
		MediaDeviceDao.videoStreamConstraints = { ...MediaDeviceDao.videoStreamConstraints, ...constraints };
		return MediaDeviceDao.videoStreamConstraints;
	}

	@log('日志消息')
	public static setAudioInputDeviceId(deviceId: string | undefined) {
		MediaDeviceDao.audioInputDeviceId = deviceId;
		this.setAudioStreamConstraints({ deviceId: MediaDeviceDao.audioInputDeviceId });
		return MediaDeviceDao.audioInputDeviceId;
	}
	@log('日志消息')
	public static setAudioOutputDeviceId(deviceId: string | undefined) {
		MediaDeviceDao.audioOutputDeviceId = deviceId;
		return MediaDeviceDao.audioOutputDeviceId;
	}

	@log('日志消息')
	public static setVideoInputDeviceId(deviceId: string | undefined) {
		MediaDeviceDao.videoInputDeviceId = deviceId;
		this.setVideoStreamConstraints({ deviceId: deviceId });
		return MediaDeviceDao.videoInputDeviceId;
	}

	@log('日志消息')
	public static setVideoOutputDeviceId(deviceId: string | undefined) {
		MediaDeviceDao.videoOutputDeviceId = deviceId;
		return MediaDeviceDao.videoOutputDeviceId;
	}

	public static setAllMediaDevices(devices: MediaDeviceInfo[]) {
		this.validMediaDevicesMap.clear();
		if (this.allMediaDevicesMap.size === 0) {
			devices.map(device => {
				if(device.deviceId) {
					this.allMediaDevicesMap.set(`${device.kind}-${device.deviceId}`, device)
				}
			});
		}
		devices.map(device => {
			if(device.deviceId) {
				this.validMediaDevicesMap.set(`${device.kind}-${device.deviceId}`, device);
			}
			
		});
		this.devicesChange();
	}

	@log('日志消息')
	private static setAudioOutput(devices: MediaDeviceInfo[]) {
		this.audioOutput = [...devices];
		return this.audioOutput;
	}

	@log('日志消息')
	private static setAudioInput(devices: MediaDeviceInfo[]) {
		this.audioInput = [...devices];
		return this.audioInput;
	}

	@log('日志消息')
	private static setVideoInput(devices: MediaDeviceInfo[]) {
		this.videoInput = [...devices];
		return this.videoInput;
	}

	@log('日志消息')
	public static findDeviceWithDevicID(deviceId: string) {
		return [...this.validMediaDevicesMap.values()].find(item => item.deviceId === deviceId);
	}

	@log('日志消息')
	public static validateDeviceID(deviceId: string) {
		if ([...this.validMediaDevicesMap.values()].find(item => item.deviceId === deviceId)) {
			return true;
		}
		return false;
	}

	private static devicesChange() {
		const audioInputDevices: MediaDeviceInfo[] = [];
		const audioOutputDevices: MediaDeviceInfo[] = [];
		const videoInputDevices: MediaDeviceInfo[] = [];
		this.validMediaDevicesMap.forEach((value, key) => {
			if (value.deviceId !== 'communications' && value.deviceId !== 'default') {
				if (value.kind === 'audioinput') {
					audioInputDevices.push(value);
				} else if (value.kind === 'audiooutput') {
					audioOutputDevices.push(value);
				} else if (value.kind === 'videoinput') {
					videoInputDevices.push(value);
				}
			} else {
				if (value.deviceId === 'default' && (value.kind === 'audiooutput' || value.kind === 'audioinput')) {
					this.communicationsMap.set(value.kind, value);
				}
			}
		});
		this.setAudioInput(audioInputDevices);
		this.setAudioOutput(audioOutputDevices);
		this.setVideoInput(videoInputDevices);
		console.log('videoInputDevices:', this.validMediaDevicesMap);
	}

	@log('日志消息')
	public static setLocalStream(stream: MediaStream) {
		this.localStream = stream;
		return this.localStream;
	}
}

export default MediaDeviceDao;
